package com.cyan.app.workflow.common;

import android.content.Context;
import android.text.TextUtils;

import com.cyan.app.workflow.AppContext;
import com.cyan.app.workflow.AppData;
import com.cyan.app.workflow.R;
import com.cyan.app.workflow.bean.UserBean;

import com.cyan.app.workflow.util.network.CommHttpListener;
import com.cyan.app.workflow.util.network.VolleyUtil;
import com.android.volley.VolleyError;

import org.json.JSONException;
import org.json.JSONObject;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class LoginProxy {
    private static final String TAG = "LoginProxy";
    public interface LoginCallback {
        void onLoginStart(String loginType, int tag);
        void onLoginFinished(String loginType, int resultCode, String msg, int tag);
        void onLogout();
    }

    public static final String LOGIN_TYPE_USERNAME = "1";
    public static final String LOGIN_TYPE_QQ = "2";
    public static final String LOGIN_TYPE_WEIXIN = "3";


    public static final int RESULT_SUCCESS = 1;
    public static final int RESULT_FAILED_CANCEL = 2;
    public static final int RESULT_FAILED_SERVER = 3;
    public static final int RESULT_FAILED_EXCEPTION = 4;
    public static final int RESULT_FAILED_TOKEN_OUTTIME = 5;

    public static final int EXTRA_DATA_NORMAL = 0;
    public static final int EXTRA_DATA_SWITCH = 1;


    private static LoginProxy sAutoLogin;

    private List<LoginCallback> mCallbackList = new ArrayList<LoginCallback>();

    private static Context context;
    private boolean loginStateChanged;

    public static LoginProxy getInstance(Context ctx) {
        context = ctx;
        if (sAutoLogin == null) {
            synchronized (LoginProxy.class) {
                if (sAutoLogin == null) {
                    sAutoLogin = new LoginProxy();
                    sAutoLogin.setLoginStateChanged(true);
                }
            }
        }
        return sAutoLogin;
    }

    public void registerCallback(LoginCallback callback) {
        synchronized (mCallbackList) {
            if (!mCallbackList.contains(callback)) {
                mCallbackList.add(callback);
            }
        }
    }

    public void unRegisterCallback(LoginCallback callback) {
        synchronized (mCallbackList) {
            if (mCallbackList.contains(callback)) {
                mCallbackList.remove(callback);
            }
        }
    }

    public void login() {
        UserConfiger.UserLocalData userData = UserConfiger.read(AppContext.getInstance());
        if (TextUtils.isEmpty(userData.userID)) {
            return;
        }
        try {
            JSONObject param = new JSONObject();
            param.put("usertype", userData.userType);
            param.put("UserNo", userData.userID);
            param.put("Token", userData.userToken);
            param.put("name", "");
            param.put("Password", "");
            param.put("FacNo", HttpConfig.Main_FacNo);


            login(param, EXTRA_DATA_NORMAL);

        } catch (JSONException e) {
        }
    }

    public void login(JSONObject jsonParam, final int tag) {
        String loginType = LOGIN_TYPE_USERNAME;
        try {
            loginType = jsonParam.getString("usertype");
        } catch (JSONException e) {
        }

        notifyLoginStart(loginType, tag);
        Map<String, String> params = new HashMap<String, String>();
      //  params.put("action", "login");
        params.put("paramstr", jsonParam.toString());

        final String finalLoginType = loginType;
 //       VolleyUtil.sendStringRequestByGet(context, TAG, params, UserBean.class, new CommHttpListener<UserBean>() {
        VolleyUtil.sendStringRequestByGet(context,HttpConfig.HTTP_MAIN_BASE_URL+"/api/login" ,TAG, params, UserBean.class, new CommHttpListener<UserBean>() {
            @Override
            public void onSuccess(UserBean userBean) {
                UserConfiger.UserLocalData userData = new UserConfiger.UserLocalData();
                userData.userID = userBean.getResult().getUserNo();
                userData.userName = userBean.getResult().getUserName();
                userData.userType = String.valueOf(userBean.getResult().getUserType());
                userData.userToken = userBean.getResult().getToken();
                userData.userConnect = userBean.getResult().getConnectstring();
                notifyLoginResult(userData, finalLoginType, RESULT_SUCCESS, "", tag);
            }

            @Override
            public void onCodeError(int code, String msg) {
                if (code == -2) {
                    notifyLoginResult(null, finalLoginType, RESULT_FAILED_TOKEN_OUTTIME, msg, tag);
                } else {
                    notifyLoginResult(null, finalLoginType, RESULT_FAILED_SERVER, msg, tag);
                }
            }

            @Override
            public void onVolleyError(VolleyError volleyError) {
                notifyLoginResult(null, finalLoginType, RESULT_FAILED_SERVER, AppContext.getInstance().getResources().getString(R.string.network_error), tag);
            }

            @Override
            public void onException(Exception e) {
                notifyLoginResult(null, finalLoginType, RESULT_FAILED_EXCEPTION, AppContext.getInstance().getResources().getString(R.string.network_error), tag);
            }
        });
    }

    public void login(UserBean userBean) {
        UserConfiger.UserLocalData userData = new UserConfiger.UserLocalData();
        userData.userID = userBean.getResult().getUserNo();
        userData.userName = userBean.getResult().getUserName();
        userData.userType = String.valueOf(userBean.getResult().getUserType());
        userData.userToken = userBean.getResult().getToken();
        userData.userConnect = userBean.getResult().getConnectstring();
        notifyLoginResult(userData, String.valueOf(userBean.getResult().getUserType()), RESULT_SUCCESS, "", EXTRA_DATA_NORMAL);
    }

    public void logout() {
        UserConfiger.clear(AppContext.getInstance());
        AppData.getInstance().clear();
        notifyLogout();
    }

    public void notifyLoginResult(UserConfiger.UserLocalData userData, String loginType, int resultCode, String msg, int tag) {
        if (userData == null) {
            AppData.getInstance().clear();

            if (resultCode == RESULT_FAILED_TOKEN_OUTTIME) {
                UserConfiger.clear(AppContext.getInstance());
            }
        } else {
            setLoginStateChanged(true);

            AppData.getInstance().setUserName(userData.userName);
            AppData.getInstance().setUserId(userData.userID);
            AppData.getInstance().setUserType(userData.userType);
            AppData.getInstance().setUserToken(userData.userToken);
            AppData.getInstance().setConnectstring(userData.userConnect);
            UserConfiger.save(AppContext.getInstance(), userData);
        }

        notifyLoginFinished(loginType, resultCode, msg, tag);
    }

    private List<LoginCallback> copyCallbackListSafe() {
        List<LoginCallback> callbackList = new ArrayList<LoginCallback>();
        synchronized (mCallbackList) {
            for (LoginCallback callback : mCallbackList) {
                callbackList.add(callback);
            }
        }
        return callbackList;
    }

    public void notifyLogout() {
        List<LoginCallback> callbackList = copyCallbackListSafe();
        for (LoginCallback callback : callbackList) {
            callback.onLogout();
        }
    }

    private void notifyLoginStart(String loginType, int tag) {
        List<LoginCallback> callbackList = copyCallbackListSafe();
        for (LoginCallback callback : callbackList) {
            callback.onLoginStart(loginType, tag);
        }
    }

    private void notifyLoginFinished(String loginType, int resultCode, String msg, int tag) {
        List<LoginCallback> callbackList = copyCallbackListSafe();
        for (LoginCallback callback : callbackList) {
            callback.onLoginFinished(loginType, resultCode, msg, tag);
        }
    }

    public boolean isLoginStateChanged() {
        return loginStateChanged;
    }

    public void setLoginStateChanged(boolean loginStateChanged) {
        this.loginStateChanged = loginStateChanged;
    }
}